classdef SecondOrdStage < handle
    properties
        transferFunction;
        poles; %rad/s
        zeros; %rad/s
        k;
        Q;
        Finf; %Hz
        F0; %Hz
        Gi; %dB
        dinRang; %dB
        FilterType;
        
        freq = []; %Hz
        attenuation = []; %dB
    end
    
    methods
        
        function this = SecondOrdStage(poles, zeros, Q, freq)
            this.poles = poles;
            this.zeros = zeros;
            this.setFilterType(poles,zeros);
            this.k = 1;
            if ~isempty(Q)
                this.Q = Q;
            else
                this.Q = NaN;
            end
            this.freq = freq;
            if ~isempty(this.poles)  
                this.F0 = abs(this.poles(1))/(2*pi);
            else
                this.F0 = NaN;
            end
            if ~isempty(this.zeros)
                this.Finf = abs(imag(this.zeros(1))/(2*pi));
            else
                this.Finf = NaN;
            end

            num = poly(this.zeros);
            den = poly(this.poles);
            this.transferFunction = tf(num, den);
            
            switch this.FilterType
                case {'LowPassFirstOrd', 'LowPassSecondOrd', 'LowPassNotch', 'BandReject'}
                    atte0 = bode(this.transferFunction, 0); 
                case {'HighPassFirstOrd', 'HighPassSecondOrd', 'HighPassNotch'}
                    atte0 = bode(this.transferFunction, inf);
                case 'BandPass'
                    atte0 = bode(this.transferFunction, this.F0*2*pi);
                case 'GainStage'
                    atte0 = 1;
            end
            this.transferFunction = this.transferFunction/atte0;
            [this.attenuation ~] = bode(this.transferFunction, this.freq*(2*pi));
            this.attenuation = -20*log10(squeeze(this.attenuation));
            
            this.Gi = 1;
%             this.dinRang = 100;
        end
        
        function setGain(this, gain, change)
            if change
                this.transferFunction = this.transferFunction * gain / this.Gi;
                [this.attenuation ~] = bode(this.transferFunction, this.freq*(2*pi));
                this.attenuation = -20*log10(squeeze(this.attenuation));
            end
            this.Gi = gain;
        end
        
        function setFilterType(obj,poles,zeros)
            
            if isempty(poles) && isempty(zeros)
                obj.FilterType = 'GainStage';
                return;
            end
            polesSize = size(poles);
            if polesSize(2) > 1
                poles = poles';
            end
            zerosSize = size(zeros);
            if zerosSize(2) > 1
                zeros = zeros';
            end
            
            if length(poles) == 1
                if ~isempty(zeros)
                    obj.FilterType = 'HighPassFirstOrd';
                else
                    obj.FilterType = 'LowPassFirstOrd';
                end
            else
                if isempty(zeros)
                    obj.FilterType = 'LowPassSecondOrd';
                else
                    if length(zeros) == 1
                        obj.FilterType = 'BandPass';
                    else
                        if zeros(1) == 0
                            obj.FilterType = 'HighPassSecondOrd';
                        else
                            if abs(zeros) < abs (poles)
                                obj.FilterType = 'HighPassNotch';
                            else
                                if abs(zeros) == abs(poles)
                                    obj.FilterType = 'BandReject';
                                else
                                    obj.FilterType = 'LowPassNotch';
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
    
        